package org.example.wx.service;

import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class MinioService {

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucket-name:wxwby}")
    private String bucketName;

    @Value("${minio.endpoint:http://39.96.219.197:9000}")
    private String endpoint;

    /**
     * 检查存储桶是否存在，不存在则创建
     */
    public void createBucketIfNotExists() throws Exception {
        try {
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(bucketName)
                    .build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(bucketName)
                        .build());
                log.info("Created bucket: {}", bucketName);
            }
        } catch (Exception e) {
            log.error("MinIO connection error. Please check endpoint configuration. Current endpoint: {}", endpoint);
            log.error("If you see 'S3 API Request made to Console port' error, try changing the port from 9000 to 9001 or vice versa");
            log.error("MinIO error details: {}", e.getMessage());
            // 不抛出异常，允许应用继续运行
        }
    }

    /**
     * 上传文件
     * @param file 文件
     * @param folder 文件夹名称
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file, String folder) throws Exception {
        try {
            createBucketIfNotExists();

            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String extension = "";
            if (originalFilename != null && originalFilename.contains(".")) {
                extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            }
            String fileName = folder + "/" + UUID.randomUUID().toString() + extension;

            // 上传文件
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build());

            // 生成预签名URL (7天有效)
            String objectName = fileName;
            try {
                String url = minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(7 * 24 * 3600) // 7天有效期
                        .build()
                );
                log.info("文件上传成功到MinIO，预签名URL: {}", url);
                return url;
            } catch (Exception e) {
                log.warn("生成预签名URL失败，返回普通URL: {}", e.getMessage());
                // 如果预签名失败，返回普通URL
                String fileUrl = endpoint + "/" + bucketName + "/" + fileName;
                log.info("文件上传成功到MinIO: {}", fileUrl);
                return fileUrl;
            }
            
        } catch (Exception e) {
            log.error("MinIO上传失败，使用本地存储作为备用方案: {}", e.getMessage());
            
            // 备用方案：返回一个临时的本地路径标识
            // 在实际项目中，这里可以实现本地文件存储
            String tempFileName = folder + "_" + UUID.randomUUID().toString() + 
                (file.getOriginalFilename() != null && file.getOriginalFilename().contains(".") ? 
                    file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")) : "");
            
            log.warn("返回临时文件标识: {}", tempFileName);
            throw new RuntimeException("MinIO服务暂时不可用: " + e.getMessage());
        }
    }

    /**
     * 上传字节数组
     * @param data 文件数据
     * @param fileName 文件名
     * @param contentType 内容类型
     * @param folder 文件夹名称
     * @return 文件访问URL
     */
    public String uploadFile(byte[] data, String fileName, String contentType, String folder) throws Exception {
        createBucketIfNotExists();

        // 生成唯一文件名
        String extension = "";
        if (fileName != null && fileName.contains(".")) {
            extension = fileName.substring(fileName.lastIndexOf("."));
        }
        String uniqueFileName = folder + "/" + UUID.randomUUID().toString() + extension;

        // 上传文件
        InputStream inputStream = new ByteArrayInputStream(data);
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(uniqueFileName)
                        .stream(inputStream, data.length, -1)
                        .contentType(contentType)
                        .build());

        // 返回文件访问URL
        return endpoint + "/" + bucketName + "/" + uniqueFileName;
    }

    /**
     * 删除文件
     * @param fileName 文件名
     */
    public void deleteFile(String fileName) throws Exception {
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .build());
    }

    /**
     * 获取文件预签名URL（临时访问链接）
     * @param fileName 文件名
     * @param expiry 过期时间（秒）
     * @return 预签名URL
     */
    public String getPresignedUrl(String fileName, int expiry) throws Exception {
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(fileName)
                        .expiry(expiry)
                        .build());
    }

    /**
     * 列出所有存储桶
     * @return 存储桶列表
     */
    public List<Bucket> listBuckets() throws Exception {
        return minioClient.listBuckets();
    }
}
